home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / r_light.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  6KB  |  261 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_light.c
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. int    r_dlightframecount;
  26.  
  27.  
  28. /*
  29. ==================
  30. R_AnimateLight
  31. ==================
  32. */
  33. void R_AnimateLight (void)
  34. {
  35.     int            i,j,k;
  36.     
  37. //
  38. // light animations
  39. // 'm' is normal light, 'a' is no light, 'z' is double bright
  40.     i = (int)(cl.time*10);
  41.     for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
  42.     {
  43.         if (!cl_lightstyle[j].length)
  44.         {
  45.             d_lightstylevalue[j] = 256;
  46.             continue;
  47.         }
  48.         k = i % cl_lightstyle[j].length;
  49.         k = cl_lightstyle[j].map[k] - 'a';
  50.         k = k*22;
  51.         d_lightstylevalue[j] = k;
  52.     }    
  53. }
  54.  
  55.  
  56. /*
  57. =============================================================================
  58.  
  59. DYNAMIC LIGHTS
  60.  
  61. =============================================================================
  62. */
  63.  
  64. /*
  65. =============
  66. R_MarkLights
  67. =============
  68. */
  69. void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
  70. {
  71.     mplane_t    *splitplane;
  72.     float        dist;
  73.     msurface_t    *surf;
  74.     int            i;
  75.     
  76.     if (node->contents < 0)
  77.         return;
  78.  
  79.     splitplane = node->plane;
  80.     dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
  81.     
  82.     if (dist > light->radius)
  83.     {
  84.         R_MarkLights (light, bit, node->children[0]);
  85.         return;
  86.     }
  87.     if (dist < -light->radius)
  88.     {
  89.         R_MarkLights (light, bit, node->children[1]);
  90.         return;
  91.     }
  92.         
  93. // mark the polygons
  94.     surf = cl.worldmodel->surfaces + node->firstsurface;
  95.     for (i=0 ; i<node->numsurfaces ; i++, surf++)
  96.     {
  97.         if (surf->dlightframe != r_dlightframecount)
  98.         {
  99.             surf->dlightbits = 0;
  100.             surf->dlightframe = r_dlightframecount;
  101.         }
  102.         surf->dlightbits |= bit;
  103.     }
  104.  
  105.     R_MarkLights (light, bit, node->children[0]);
  106.     R_MarkLights (light, bit, node->children[1]);
  107. }
  108.  
  109.  
  110. /*
  111. =============
  112. R_PushDlights
  113. =============
  114. */
  115. void R_PushDlights (void)
  116. {
  117.     int        i;
  118.     dlight_t    *l;
  119.  
  120.     r_dlightframecount = r_framecount + 1;    // because the count hasn't
  121.                                             //  advanced yet for this frame
  122.     l = cl_dlights;
  123.  
  124.     for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
  125.     {
  126.         if (l->die < cl.time || !l->radius)
  127.             continue;
  128.         R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
  129.     }
  130. }
  131.  
  132.  
  133. /*
  134. =============================================================================
  135.  
  136. LIGHT SAMPLING
  137.  
  138. =============================================================================
  139. */
  140.  
  141. int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
  142. {
  143.     int            r;
  144.     float        front, back, frac;
  145.     int            side;
  146.     mplane_t    *plane;
  147.     vec3_t        mid;
  148.     msurface_t    *surf;
  149.     int            s, t, ds, dt;
  150.     int            i;
  151.     mtexinfo_t    *tex;
  152.     byte        *lightmap;
  153.     unsigned    scale;
  154.     int            maps;
  155.  
  156.     if (node->contents < 0)
  157.         return -1;        // didn't hit anything
  158.     
  159. // calculate mid point
  160.  
  161. // FIXME: optimize for axial
  162.     plane = node->plane;
  163.     front = DotProduct (start, plane->normal) - plane->dist;
  164.     back = DotProduct (end, plane->normal) - plane->dist;
  165.     side = front < 0;
  166.     
  167.     if ( (back < 0) == side)
  168.         return RecursiveLightPoint (node->children[side], start, end);
  169.     
  170.     frac = front / (front-back);
  171.     mid[0] = start[0] + (end[0] - start[0])*frac;
  172.     mid[1] = start[1] + (end[1] - start[1])*frac;
  173.     mid[2] = start[2] + (end[2] - start[2])*frac;
  174.     
  175. // go down front side    
  176.     r = RecursiveLightPoint (node->children[side], start, mid);
  177.     if (r >= 0)
  178.         return r;        // hit something
  179.         
  180.     if ( (back < 0) == side )
  181.         return -1;        // didn't hit anuthing
  182.         
  183. // check for impact on this node
  184.  
  185.     surf = cl.worldmodel->surfaces + node->firstsurface;
  186.     for (i=0 ; i<node->numsurfaces ; i++, surf++)
  187.     {
  188.         if (surf->flags & SURF_DRAWTILED)
  189.             continue;    // no lightmaps
  190.  
  191.         tex = surf->texinfo;
  192.         
  193.         s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
  194.         t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
  195.  
  196.         if (s < surf->texturemins[0] ||
  197.         t < surf->texturemins[1])
  198.             continue;
  199.         
  200.         ds = s - surf->texturemins[0];
  201.         dt = t - surf->texturemins[1];
  202.         
  203.         if ( ds > surf->extents[0] || dt > surf->extents[1] )
  204.             continue;
  205.  
  206.         if (!surf->samples)
  207.             return 0;
  208.  
  209.         ds >>= 4;
  210.         dt >>= 4;
  211.  
  212.         lightmap = surf->samples;
  213.         r = 0;
  214.         if (lightmap)
  215.         {
  216.  
  217.             lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
  218.  
  219.             for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
  220.                     maps++)
  221.             {
  222.                 scale = d_lightstylevalue[surf->styles[maps]];
  223.                 r += *lightmap * scale;
  224.                 lightmap += ((surf->extents[0]>>4)+1) *
  225.                         ((surf->extents[1]>>4)+1);
  226.             }
  227.             
  228.             r >>= 8;
  229.         }
  230.         
  231.         return r;
  232.     }
  233.  
  234. // go down back side
  235.     return RecursiveLightPoint (node->children[!side], mid, end);
  236. }
  237.  
  238. int R_LightPoint (vec3_t p)
  239. {
  240.     vec3_t        end;
  241.     int            r;
  242.     
  243.     if (!cl.worldmodel->lightdata)
  244.         return 255;
  245.     
  246.     end[0] = p[0];
  247.     end[1] = p[1];
  248.     end[2] = p[2] - 2048;
  249.     
  250.     r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
  251.     
  252.     if (r == -1)
  253.         r = 0;
  254.  
  255.     if (r < r_refdef.ambientlight)
  256.         r = r_refdef.ambientlight;
  257.  
  258.     return r;
  259. }
  260.  
  261.